package za.org.meraka.cair.ontorepair;

import org.protege.editor.core.ui.list.MList;
import org.protege.editor.core.ui.list.MListButton;
import org.protege.editor.owl.OWLEditorKit;
import org.protege.editor.owl.ui.framelist.ExplainButton;
import org.protege.editor.owl.ui.renderer.LinkedObjectComponent;
import org.protege.editor.owl.ui.renderer.LinkedObjectComponentMediator;
import org.protege.editor.owl.ui.view.Copyable;
import org.semanticweb.owlapi.model.*;

import za.org.meraka.cair.ontorepair.JustificationListItem;
import za.org.meraka.cair.ontorepair.JustificationSection;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;

public class JustificationList extends MList implements LinkedObjectComponent, Copyable {

    private OWLEditorKit owlEditorKit;
    
    private LinkedObjectComponentMediator mediator;

    private List<ChangeListener> copyListeners = new ArrayList<ChangeListener>();

    public JustificationList(OWLEditorKit owlEditorKit) {
        this.owlEditorKit = owlEditorKit;
        setCellRenderer(new JustificationListCellRenderer(owlEditorKit));
        explainButton.add(new ExplainButton(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

            }
        }));
        mediator = new LinkedObjectComponentMediator(owlEditorKit, this);

        getSelectionModel().addListSelectionListener(new ListSelectionListener(){
            public void valueChanged(ListSelectionEvent event) {
                ChangeEvent ev = new ChangeEvent(JustificationList.this);
                for (ChangeListener l : copyListeners){
                    l.stateChanged(ev);
                }
            }
        });
    }
    
    private List<MListButton> explainButton = new ArrayList<MListButton>();
   
    public void displayJustifications(FullJustification just){
    		List data = new ArrayList();    		    		
    		int count1 = 1;
    		data.add(new JustificationSection(just.getAxiomRendering() + ":"));
    		for (Justification j: just.justifications){
    			data.add(new JustificationSection("Justification " + count1 + " of " + just.justifications.size() + ": ( " + j.justification.size() + " axioms )"));
    			for (OWLAxiom a: j.justification){
    				data.add(new JustificationListItem(a));
    			}
    			count1++;    			
    		}    			    			
    	            
    		setListData(data.toArray());       
    }
    
    public void displayRootRepairSets(Set<Justification> just){
		List data = new ArrayList();		
		Set<OWLAxiom> axioms = new HashSet<OWLAxiom>();
		int count1 = 1;            
		for (Justification j: just){
			data.add(new JustificationSection("Root Repair set " + count1 + " of " + just.size() + ": ( " + j.justification.size() + " axioms )"));
			
			for (OWLAxiom a: j.justification)
				data.add(new JustificationListItem(a));
			
			count1++;						
		}		    			    				        
		setListData(data.toArray());       
    }
    
    public void displayNaiveRepairSets(Set<Justification> just){
		List data = new ArrayList();		
		Set<OWLAxiom> axioms = new HashSet<OWLAxiom>();
		int count1 = 1;            
		for (Justification j: just){
			data.add(new JustificationSection("Naive Repair set " + count1 + ": ( " + j.justification.size() + " axioms )"));
			
			for (OWLAxiom a: j.justification)
				data.add(new JustificationListItem(a));
			
			count1++;						
		}		    			    				        
		setListData(data.toArray());       
    }
    
    public void displayRootJustifications(Set<Justification> just){
		List data = new ArrayList();		
		Set<OWLAxiom> axioms = new HashSet<OWLAxiom>();
		int count1 = 1;            
		for (Justification j: just){
			data.add(new JustificationSection("ROOT Justification " + count1 + " of " + just.size() + ": ( " + j.justification.size() + " axioms )"));
			
			for (OWLAxiom a: j.justification)
				data.add(new JustificationListItem(a));
			
			count1++;						
		}		    			    				        
		setListData(data.toArray());       
    }

    protected List<MListButton> getButtons(Object value) {
        // TODO: Would be nice :)
//        if (value instanceof DLQueryResultsSectionItem) {
//            return explainButton;
//        }
//        else {
        return Collections.emptyList();
//        }
    }
    
    public JComponent getComponent() {
        return this;
    }

    public OWLObject getLinkedObject() {
        return mediator.getLinkedObject();
    }

    public Point getMouseCellLocation() {
        Rectangle r = getMouseCellRect();
        if (r == null) {
            return null;
        }
        Point mousePos = getMousePosition();
        if (mousePos == null) {
            return null;
        }
        return new Point(mousePos.x - r.x, mousePos.y - r.y);
    }

    public Rectangle getMouseCellRect() {
        Point mousePos = getMousePosition();
        if (mousePos == null) {
            return null;
        }
        int sel = locationToIndex(mousePos);
        if (sel == -1) {
            return null;
        }
        return getCellBounds(sel, sel);
    }

    public void setLinkedObject(OWLObject object) {
        mediator.setLinkedObject(object);
    }

    public boolean canCopy() {
        return getSelectedIndices().length > 0;
    }

    public List<OWLObject> getObjectsToCopy() {
        List<OWLObject> copyObjects = new ArrayList<OWLObject>();
        for (Object sel : getSelectedValues()){
            if (sel instanceof JustificationListItem){
                copyObjects.add(((JustificationListItem)sel).getOWLObject());
            }
        }
        return copyObjects;
    }

    public void addChangeListener(ChangeListener changeListener) {
        copyListeners.add(changeListener);
    }

    public void removeChangeListener(ChangeListener changeListener) {
        copyListeners.remove(changeListener);
    }
}
